<?php
/*
 * [insert-quote]
 * 
 * @author: Blagovest Gospodinov
 */

class Core_Utility_ArrayAccess{
	const KEY_ERROR_TEMPLATE = 'Key "%s" not found';
	const VALUE_ERROR_TEMPLATE = 'Compound key ("%s") used on a non-array value';
	
	static public function &read( &$array, $key ){
		$key = explode( '.' , $key );
		
		$at = &$array;
		
		for( $i = 0 ; $i < sizeof($key) ; $i++ ){
			$currKey = $key[$i];
						
			if( !is_array( $at ) ){
				if( !($at instanceof ArrayAccess) )
					throw new Core_Exception_Registry_ValueError( sprintf(self::VALUE_ERROR_TEMPLATE, $currKey) ); /// throw!
			}
			
			if( !isset( $at[$currKey] ) )
				throw new Core_Exception_Registry_KeyError( sprintf(self::KEY_ERROR_TEMPLATE, $currKey) ); /// throw!
			
			$at = &$at[$currKey];
		}
		
		return $at; 
	}
	
	static public function &erase( &$array , $key ){
		$key = explode( '.' , $key );
		
		$at = &$array;
		
		for( $i = 0 ; $i < sizeof($key) ; $i++ ){
			$currKey = $key[$i];
			
			if( !is_array( $at ) ){
				if( !($at instanceof ArrayAccess) )
					throw new Core_Exception_Registry_ValueError( sprintf(self::VALUE_ERROR_TEMPLATE, $currKey) ); /// throw!
			}
			
			if( !isset( $at[$currKey] ) ){
				throw new Core_Exception_Registry_KeyError( sprintf(self::KEY_ERROR_TEMPLATE, $currKey) );
			}
			
			if( $i != sizeof($key) - 1 )
				$at = &$at[$currKey];
			else
				unset( $at[$currKey] );
		}
		
		return $at;
	}
	
	static public function &write( &$array , $key , $value = null , $object = null ){
		$key = explode( '.' , $key );
	
		$at = &$array;
	
		for( $i = 0 ; $i < sizeof($key) ; $i++ ){
			$currKey = $key[$i];
				
			if( !is_array( $at ) ){
				if( !($at instanceof ArrayAccess) )
					throw new Core_Exception_Registry_ValueError( sprintf(self::VALUE_ERROR_TEMPLATE, $currKey) ); /// throw!
			}
	
			if( !isset( $at[$currKey] ) ){
				if( $i != sizeof($key) - 1 ){
					if( $object === null )
						$at[$currKey] = array();
					else
						$at[$currKey] = new $object;
				}else{
					$at[$currKey] = $value;
				}
			}
				
			$at = &$at[$currKey];
		}
	
		return $at;
	}
	
	static public function has( &$array , $key ){
		$key = explode( '.' , $key );
	
		$at = &$array;
	
		for( $i = 0 ; $i < sizeof($key) ; $i++ ){
			$currKey = $key[$i];
	
			if( !is_array( $at ) ){
				if( !($at instanceof ArrayAccess) )
					return false;
			}
			
			if( !isset( $at[$currKey] ) ){
				return false;
			}
	
			$at = &$at[$currKey];
		}
		
		return true;
	}
}
